package it.maganar.lesscaos.session;

import it.maganar.lesscaos.entity.Disponibilita;
import it.maganar.lesscaos.entity.Negoziazione;
import it.maganar.lesscaos.entity.Tappa;
import it.maganar.lesscaos.entity.User;
import it.maganar.lesscaos.exception.UserNotLoggedException;
import it.maganar.lesscaos.util.TipoVeicolo;

import java.sql.Date;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateful;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
 * Session Bean implementation class ServiceGate
 */
@SuppressWarnings("unchecked")
@Stateful
public class ServiceGate implements ServiceGateRemote {

	@EJB
    private RegistrationManagerLocal rml;
	private DisponibilitaGiornalieraManagerLocal dgml;
	private DisponibilitaOccasionaleManagerLocal doml;
	private DisponibilitaManagerLocal dml;
	private PartecipazioniManagerLocal pml;
	private NegoziazioniManagerLocal nml;
	
	@PersistenceContext(unitName="lessDB")
	private EntityManager manager;
	
	private User u;
	
    public ServiceGate() {
    	
    	u = null;
    	try {
	        Context jndiContext = new InitialContext(); 
	        
			Object ref = jndiContext.lookup("Less-CAOS/RegistrationManagerBean/local");
			rml = (RegistrationManagerLocal)ref;
			
			ref = jndiContext.lookup("Less-CAOS/DisponibilitaGiornalieraManagerBean/local");
			dgml = (DisponibilitaGiornalieraManagerLocal)ref;
			
			ref = jndiContext.lookup("Less-CAOS/DisponibilitaOccasionaleManagerBean/local");
			doml = (DisponibilitaOccasionaleManagerLocal)ref;
			
			ref = jndiContext.lookup("Less-CAOS/DisponibilitaManagerBean/local");
			dml = (DisponibilitaManagerLocal)ref;
			
			ref = jndiContext.lookup("Less-CAOS/PartecipazioniManagerBean/local");
			pml = (PartecipazioniManagerLocal)ref;
			
			ref = jndiContext.lookup("Less-CAOS/NegoziazioniManagerBean/local");
			nml = (NegoziazioniManagerLocal)ref;
			
		} catch (NamingException e) {
			e.printStackTrace();
		}

    }
    
    // ======== Generali =============
    
    public boolean inserisciRegistrazione(String nomeUtente, String password, String nome, String cognome, String nTelefono) {
    	//controllo sui valori inseriti
    	if (nomeUtente == null || password == null || nome == null || cognome == null || nTelefono == null) {
    		return false;
    	}
    	return rml.inserisciRegistrazione(nomeUtente, password, nome, cognome, nTelefono);
    }
    
    public boolean login(String nomeUtente, String password){
    	User toBeControlled = new User();
    	toBeControlled = manager.find(User.class, nomeUtente);
    	//nomeUtente non trovato
    	if (toBeControlled == null) {
    		return false;
    	}
    	//password errata
    	else if (!toBeControlled.getPassword().equals(password)) {
    		return false;
    	}
    	else if (toBeControlled.getPassword().equals(password)) {
    		u = toBeControlled;
    		return true;
    	}    
    	return false;
    }
    
    public void logout() {
    	u = null;
    }
    
    // ======== Disponibilita =============

    public boolean inserisciDisponibilita(int numPosti, TipoVeicolo tipoVeicolo,
    		Date data, Tappa partenza, Tappa arrivo, List listaTappe, boolean occasionale) throws UserNotLoggedException {
    	
    	if (u == null) {
    		throw new UserNotLoggedException();
    	}
    	
    	//controllo sui valori inseriti
    	boolean errore = false;
    	if (numPosti > tipoVeicolo.posti() ) {
    		System.out.println("ERRORE: il numero di posti specificato è maggiore del numero posti totale disponibile");
    		errore = true;
    	}
    	if(numPosti < 0) {
    		System.out.println("ERRORE: il numero di posti specificato è negativo");
    		errore = true;
    	}
    	if(occasionale == true && data == null) {
    		System.out.println("ERRORE: viaggio occasionale, specificare un valore per la data");
    		errore = true;
    	}
    	if(tipoVeicolo == null || partenza == null || arrivo == null) {
    		System.out.println("ERRORE: un valore obbligatorio è stato impostato a null");
    		errore = true;
    	} else {
    		//partenza e arrivo non null
    		if (partenza.getIndirizzo().equals(arrivo.getIndirizzo())) {
        		System.out.println("ERRORE: percorso circolare non consentiti");
        		errore = true;
        	}
    		if (partenza.getOrario().after(arrivo.getOrario()) || partenza.getOrario().equals(arrivo.getOrario())) {
        		System.out.println("ERRORE: orario di partenza >= orario d'arrivo");
        		errore = true;
        	}
    		if (listaTappe != null) {
    			//controllo ogni tappa con patenza e arrivo
    			for(int i = 0; i < listaTappe.size(); i++) {
    				Tappa t = ((List<Tappa>)listaTappe).get(i);
    				if (t.getIndirizzo().equals(partenza.getIndirizzo()) || t.getIndirizzo().equals(arrivo.getIndirizzo())) {
    					System.out.println("ERRORE: percorso che passa da uno stesso punto");
    					errore = true;
    				}
    				if (t.getOrario().after(arrivo.getOrario()) || t.getOrario().before(partenza.getOrario())) {
    					System.out.println("ERRORE: orario di una tappa non compatibile con partenza o arrivo");
    					errore = true;
    				}
    			}
    			//controllo le tappe tra loro
    			for(int i = 0; i < listaTappe.size() - 1; i++) {
    				Tappa t = ((List<Tappa>)listaTappe).get(i);
    				for(int j = i+1; j < listaTappe.size(); j++) {
    					Tappa t1 = ((List<Tappa>)listaTappe).get(j);
    					if (t.getIndirizzo().equals(t1.getIndirizzo())) {
        					System.out.println("ERRORE: percorso che passa da uno stesso punto");
        					errore = true;
        				}
    					if (t.getOrario().after(t1.getOrario())) {
    						System.out.println("ERRORE: orario di una tappa non compatibile con una tappa successiva");
        					errore = true;
    					}
    				}
    			}
    		}
    	}
    	if (errore) {
    		return false;
    	}
    	
    	//sono qui se non ci sono errori
    	Disponibilita d = new Disponibilita();
    	d.setNumPosti(numPosti);
    	d.setTipoVeicolo(tipoVeicolo);
    	d.setPartenza(partenza);
    	d.setArrivo(arrivo);
    	d.setOrarioPart(d.getPartenza().getOrario());
    	d.setOrarioArr(d.getArrivo().getOrario());
    	d.setPartenza(partenza);
    	d.setArrivo(arrivo);
    	d.setListaTappe(listaTappe);
    	d.setIssuer(u);
    	
		if (occasionale) {
			d.setData(data);
			return doml.inserisciDisponibilitaOccasionale(u,d);
		}
		else {
			d.setData(null);
			return dgml.inserisciDisponibilitaGiornaliera(u,d);
		}
	}
	
	public void eliminaDisponibilita(int id) throws UserNotLoggedException{
		if (u == null) {
    		throw new UserNotLoggedException();
    	}
		dml.eliminaDisponibilita(id, u.getNomeUtente());
	}

	public List ottieniListaDisponibilita() throws UserNotLoggedException {
		if (u == null) {
    		throw new UserNotLoggedException();
    	}
		return dml.ottieniListaDisponibilita(u.getNomeUtente());
	}

	public List ottieniListaPartecipazioniDisponibilita(int id) throws UserNotLoggedException {
		if (u == null) {
    		throw new UserNotLoggedException();
    	}
		return dml.ottieniListaPartecipazioniDisponibilita(u.getNomeUtente(), id);
	}
	
	// ======== Partecipazioni =============
	
	public boolean inserisciPercorso(Disponibilita iscrizione, Tappa partenza, Tappa arrivo) throws UserNotLoggedException {
		if (u == null) {
    		throw new UserNotLoggedException();
    	}
		return pml.inserisciPercorso(u.getNomeUtente(), iscrizione, partenza, arrivo);
		
	}

	public List ottieniListaPercorsi(String partenza, String arrivo, boolean includi_parziali) throws UserNotLoggedException {
		if (u == null) {
    		throw new UserNotLoggedException();
    	}
		return pml.ottieniListaPercorsi(partenza, arrivo, includi_parziali);
	}

	public List ottieniListaPartecipazioni() throws UserNotLoggedException {
		if (u == null) {
    		throw new UserNotLoggedException();
    	}
		return pml.ottieniListaPartecipazioni(u.getNomeUtente());
	}

	public void eliminaPartecipazione(int id) throws UserNotLoggedException {
		if (u == null) {
    		throw new UserNotLoggedException();
    	}
		pml.eliminaPartecipazione(id, u.getNomeUtente());
		
	}
    
	// ======== Negoziazioni =============
	
	public boolean accettaCondizione(Negoziazione n) throws UserNotLoggedException {
		if (u == null) {
    		throw new UserNotLoggedException();
    	}
		return nml.accettaCondizioni(u.getNomeUtente(), n);
		
	}

	public boolean aggiungiCondizione(Negoziazione n, String condizione) throws UserNotLoggedException {
		if (u == null) {
    		throw new UserNotLoggedException();
    	}
		return nml.aggiungiCondizioni(u.getNomeUtente(), n, condizione);
		
	}

	public List ottieniListaNegoziazioni() throws UserNotLoggedException {
		if (u == null) {
    		throw new UserNotLoggedException();
    	}
		return nml.ottieniListaNegoziazioni(u.getNomeUtente());
	}

	public boolean rifiutaCondizione(Negoziazione n) throws UserNotLoggedException {
		if (u == null) {
    		throw new UserNotLoggedException();
    	}
		return nml.rifiutaCondizioni(u.getNomeUtente(), n);	
	}

}
